package com.starlink.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.convert.Convert;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCreateOrderResponse;
import com.lop.open.api.sdk.domain.ECAP.CommonSubscribeTraceApi.commonSubscribeTraceV1.Response;
import com.starlink.client.jd.JdClient;
import com.starlink.client.jd.properties.JdProperties;
import com.starlink.client.jd.request.CreateOrderRequest;
import com.starlink.client.jd.request.PreCheckRequest;
import com.starlink.client.jd.request.SubscribeTraceRequest;
import com.starlink.client.jd.request.base.CommonCargoInfo;
import com.starlink.client.jd.request.base.CommonProductInfo;
import com.starlink.client.jd.request.base.Contact;
import com.starlink.common.annotation.client.WeixinJsClient;
import com.starlink.common.annotation.client.base.RefundAmount;
import com.starlink.common.annotation.client.weixin.WeixinJsRefundOrderReq;
import com.starlink.common.annotation.client.weixin.WeixinJsRefundOrderRes;
import com.starlink.common.enums.ErrorCode;
import com.starlink.common.enums.OrderRefundEnum;
import com.starlink.common.enums.OrderTypeEnum;
import com.starlink.common.exception.BusinessException;
import com.starlink.context.SessionContext;
import com.starlink.mapper.*;
import com.starlink.model.domain.*;
import com.starlink.model.dtomapper.MallRefundArticlesDtoMapper;
import com.starlink.model.request.MallLogisticsRequest;
import com.starlink.model.request.MallRefundArticlesRequest;
import com.starlink.model.request.PointsUseBillRequest;
import com.starlink.model.request.mall.AdminMallLogisticsRequest;
import com.starlink.model.request.mall.AdminRefundRequest;
import com.starlink.model.request.mall.WechatRefund;
import com.starlink.model.vo.PointsVO;
import com.starlink.model.vo.mall.AdminRefundsVO;
import com.starlink.service.*;
import com.starlink.utils.IRedisCacheService;
import com.starlink.utils.MoneyUtil;
import com.starlink.utils.OrderNumUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Pageable;
import com.starlink.common.utils.AssertUtil;
import com.starlink.model.dtomapper.MallRefundsDtoMapper;
import com.starlink.model.request.MallRefundsRequest;
import com.starlink.model.util.MallRefundsConvert;
import com.starlink.model.vo.MallRefundsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.starlink.common.enums.AcquireModeEnum.TUI_KUAN;
import static com.starlink.common.enums.ActionTypeEum.CONSUMPTION_REFUND;
import static com.starlink.common.enums.BooleanEnum.FALSE;
import static com.starlink.common.enums.BooleanEnum.TRUE;
import static com.starlink.common.enums.FreeEnum.HUAN_HUO_SHIPING;
import static com.starlink.common.enums.MallBooksRasEnum.NOT_SELL;
import static com.starlink.common.enums.OrderRefundEnum.BO_HUI;
import static com.starlink.common.enums.OrderStatusEnum.*;
import static com.starlink.common.enums.OrderTypeEnum.*;
import static com.starlink.common.enums.RedisHashKeyEnum.ORDER_REFUND;
import static com.starlink.utils.IDUtils.getId;
import static com.starlink.utils.PageUtils.getOrderBy;
import static java.math.BigDecimal.ZERO;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author zhanghong
 */
@Slf4j
@Service
public class MallRefundsServiceImpl extends ServiceImpl<MallRefundsMapper, MallRefundsDO> implements MallRefundsService {
    @Autowired
    private MallRefundsMapper mallRefundsMapper;
    @Autowired
    private MallBooksOrderMapper bookOrderManager;
    @Autowired
    private MallPeripheryOrderMapper peripheryOrderMapper;
    @Autowired
    private MallPeripheryOrderService periodOrderService;
    @Autowired
    private ShoppingCartOrderMapper cartOrderManager;
    @Autowired
    private WeixinJsClient weixinJsClient;
    @Autowired
    private MallRefundArticlesMapper refundArticlesMapper;
    @Autowired
    private MallRefundArticlesService refundArticlesService;
    @Autowired
    private IRedisCacheService redisCacheService;
    @Autowired
    private PointsService pointsService;
    @Autowired
    private MallLogisticsService logisticsService;
    @Autowired
    private JdClient jdClient;
    @Autowired
    private JdProperties jdProperties;
    @Autowired
    private AddressService addressService;
    @Autowired
    private MallIntegrationOrderService integrationOrderService;
    @Autowired
    private MallBooksService bookService;
    @Autowired
    private MallBooksRasService booksRasService;
    @Autowired
    private MallOrderService mallBookOrderService;
    @Autowired
    private MallOrderDetailsService bookOrderDetailsService;
    @Autowired
    private ShoppingCartOrderService cartOrderService;
    @Autowired
    private ShoppingCartOrderDetailsService cartOrderDetailsService;
    @Autowired
    private MallPeripheryOrderDetailsService periodOrderDetailService;

    private static final long EXPIRE_SECONDS = 7 * 24 * 60 * 60; // 过期时间，单位：秒
    private static final BigDecimal MONEY = new BigDecimal(0.02);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(MallRefundsRequest request) {
        String refundReason = request.getRefundReason();
        String wxOrderNum = request.getWxOrderNum();
        List<MallRefundArticlesRequest> articlesRequests = request.getArticlesRequests();
        AssertUtil.assertNotEmpty(articlesRequests,"售后商品不能为空!");
        AssertUtil.assertNotNull(refundReason,"售后原因不能为空!");
        AssertUtil.assertNotNull(wxOrderNum,"微信支付单号不能为空!");
        if (request.getUserId() == null) {
            request.setUserId(SessionContext.getWechatUserId());
        }
        MallRefundsDO mallRefundsDO = MallRefundsDtoMapper.INSTANCE.request2DO(request);
        mallRefundsDO.setStatus(OrderRefundEnum.SHEN_PI.getType());
        Long orderId = request.getOrderId();
        Integer orderType = request.getOrderType();
        mallRefundsDO.setId(getId());
        mallRefundsMapper.insertDO(mallRefundsDO);
        Long refundsDOId = mallRefundsDO.getId();
        List<MallRefundArticlesDO> articlesDOS = articlesRequests.stream().map(item -> {
            item.setRefundId(refundsDOId);
            item.setId(getId());
            return MallRefundArticlesDtoMapper.INSTANCE.request2DO(item);
        }).collect(Collectors.toList());
        refundArticlesMapper.batchInsertDO(articlesDOS);
        //修改订单状态
        if (BOOK.getType().equals(orderType)){
            bookOrderManager.updateStatus(orderId,AFTER_SALE.getType().toString(), new Date());
            //订单商品置为已售后
            bookOrderDetailsService.lambdaUpdate()
                    .set(MallBooksOrderDetailsDO::getIsRefunds,TRUE.getCode())
                    .eq(MallBooksOrderDetailsDO::getMallBooksOrderId,orderId)
                    .update();
        }else if (RIM.getType().equals(orderType)){
            peripheryOrderMapper.updateStatus(orderId,AFTER_SALE.getType().toString(), new Date());
            //订单商品置为已售后
            periodOrderDetailService.lambdaUpdate()
                    .set(MallPeripheryOrderDetailsDO::getIsRefunds,TRUE.getCode())
                    .eq(MallPeripheryOrderDetailsDO::getMallPeripheryOrderId,orderId)
                    .update();
        }else if (OrderTypeEnum.CART.getType().equals(orderType)){
            cartOrderManager.updateStatus(orderId,AFTER_SALE.getType().toString(), new Date());
            List<Long> aticleIdList = articlesRequests.stream().map(MallRefundArticlesRequest::getArticlesId).collect(Collectors.toList());
            //订单商品置为已售后
            cartOrderDetailsService.lambdaUpdate()
                    .set(ShoppingCartOrderDetailsDO::getIsRefunds,TRUE.getCode())
                    .eq(ShoppingCartOrderDetailsDO::getShoppingCartOrderId,orderId)
                    .in(ShoppingCartOrderDetailsDO::getArticlesId,aticleIdList)
                    .update();
        }else if (OrderTypeEnum.INTEGRAL.getType().equals(orderType)){
            integrationOrderService.lambdaUpdate()
                    .set(MallIntegrationOrderDO::getStatus,AFTER_SALE.getType().toString())
                    .set(MallIntegrationOrderDO::getUpdateTime,new Date())
                    .eq(MallIntegrationOrderDO::getId,orderId)
                    .update();
            integrationOrderService.lambdaUpdate()
                    .set(MallIntegrationOrderDO::getIsRefunds,TRUE.getCode())
                    .eq(MallIntegrationOrderDO::getId,orderId)
                    .update();
        }
        return true;
    }

    @Override
    public MallRefundsVO getByKey(long id) {
        MallRefundsVO mallRefundsVO = MallRefundsDtoMapper.INSTANCE.do2VO(getById(id));
        return mallRefundsVO;
    }

    @Override
    public PageInfo<MallRefundsVO> pageQuery(Pageable pageable,MallRefundsRequest request) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), getOrderBy(pageable.getSort())).setReasonable(true);
        List<MallRefundsDO> list = mallRefundsMapper.pageQuery(request, request.getPageSize(), request.fetchOffSet());
        List<MallRefundsVO> mallRefundsVOList = MallRefundsConvert.buildMallRefundsVoList(list);
        return new PageInfo(mallRefundsVOList);
    }

    @Override
    public List<MallRefundsVO> listQuery(MallRefundsRequest request) {
        List<MallRefundsDO> list = mallRefundsMapper.selectDOList(MallRefundsDtoMapper.INSTANCE.request2DO(request));
        List<MallRefundsVO> mallRefundsVOS = MallRefundsConvert.buildMallRefundsVoList(list);
        return mallRefundsVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByKey(MallRefundsRequest request) {
        Long orderId = request.getOrderId();
        Long id = request.getId();
        AssertUtil.assertNotNull(orderId,"orderId不能为空!");
        AssertUtil.assertNotNull(id,"售后ID不能为空!");
        mallRefundsMapper.deletedByOrderId(orderId);
        refundArticlesService.lambdaUpdate().eq(MallRefundArticlesDO::getRefundId,id).remove();
        //修改订单状态
        Integer orderType = request.getOrderType();
        if (BOOK.getType().equals(orderType)){
            bookOrderManager.updateStatus(orderId,DONE.getType().toString(), new Date());
            //订单商品置为未售后
            bookOrderDetailsService.lambdaUpdate()
                    .set(MallBooksOrderDetailsDO::getIsRefunds,FALSE.getCode())
                    .eq(MallBooksOrderDetailsDO::getMallBooksOrderId,orderId)
                    .update();
        }else if (RIM.getType().equals(orderType)){
            peripheryOrderMapper.updateStatus(orderId,DONE.getType().toString(), new Date());
            periodOrderDetailService.lambdaUpdate()
                    .set(MallPeripheryOrderDetailsDO::getIsRefunds,FALSE.getCode())
                    .eq(MallPeripheryOrderDetailsDO::getMallPeripheryOrderId,orderId)
                    .update();
        }else if (OrderTypeEnum.CART.getType().equals(orderType)){
            cartOrderManager.updateStatus(orderId,DONE.getType().toString(), new Date());
            //订单商品置为未售后
            cartOrderDetailsService.lambdaUpdate()
                    .set(ShoppingCartOrderDetailsDO::getIsRefunds,FALSE.getCode())
                    .eq(ShoppingCartOrderDetailsDO::getShoppingCartOrderId,orderId)
                    .in(ShoppingCartOrderDetailsDO::getIsRefunds,TRUE.getCode())
                    .update();
        }else if (OrderTypeEnum.INTEGRAL.getType().equals(orderType)){
            integrationOrderService.lambdaUpdate()
                    .set(MallIntegrationOrderDO::getStatus,DONE.getType().toString())
                    .set(MallIntegrationOrderDO::getUpdateTime,new Date())
                    .eq(MallIntegrationOrderDO::getId,orderId)
                    .update();
            integrationOrderService.lambdaUpdate()
                    .set(MallIntegrationOrderDO::getIsRefunds,FALSE.getCode())
                    .eq(MallIntegrationOrderDO::getId,orderId)
                    .update();
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDOByIds(String ids) {
        mallRefundsMapper.deleteDOByIds(Convert.toStrArray(ids));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean free(MallRefundsRequest request) {
        String freeNum = request.getFreeNum();
        String freePicture = request.getFreePicture();
        //TODO:物流单号校验
        AssertUtil.assertNotNull(request.getId(),"售后ID不能为空");
        AssertUtil.assertNotNull(freeNum,"物流单号不能为空");
        AssertUtil.assertNotNull(freePicture,"物流单图片不能为空不能为空");
        MallRefundsDO refundsDO = MallRefundsDtoMapper.INSTANCE.request2DO(request);
        refundsDO.setStatus(OrderRefundEnum.YUN_SHU.getType());
        mallRefundsMapper.updateByOrderId(refundsDO);
        return true;
    }

    @Override
    public PageInfo<List<AdminRefundsVO>> pageList(AdminRefundRequest request, Pageable pageable) {
        PageHelper.startPage(request.getPageNum(), request.getPageSize(), getOrderBy(pageable.getSort())).setReasonable(true);
        List<AdminRefundsVO> list = mallRefundsMapper.pageList(request);
        return new PageInfo(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean approval(AdminRefundRequest request) {
        Long refundsId = request.getRefundsId();
        Integer status = request.getStatus();
        AssertUtil.assertNotNull(refundsId,"id不能为空!");
        AssertUtil.assertNotNull(status,"审批状态不能为空!");
        String overruledReason = request.getOverruledReason();
        MallRefundsDO refundsDO = new MallRefundsDO();
        if (BO_HUI.getType().equals(status)){
            AssertUtil.assertStrNotEmpty(overruledReason,"驳回原因不能为空!");
            refundsDO.setOverruledReason(overruledReason);
        }
        Long adminUserId = SessionContext.getAdminUserId();
        refundsDO.setId(refundsId);
        refundsDO.setStatus(status);
        refundsDO.setAdminId(adminUserId);
        refundsDO.setUpdateTime(new Date());
        refundsDO.setUpdateUser(adminUserId);
        mallRefundsMapper.updateDO(refundsDO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean pass(AdminRefundRequest request, WechatRefund wechatRefund) {
        Long adminUserId = SessionContext.getAdminUserId();
        Long refundsId = request.getRefundsId();
        Long userId = request.getUserId();
        String orderType = request.getOrderType();
        Long orderId = request.getOrderId();
        String wxOrderNum = request.getWxOrderNum();
        AssertUtil.assertNotNull(wxOrderNum,"微信订单号不能为空!");
        AssertUtil.assertNotNull(orderId,"订单ID不能为空!");
        AssertUtil.assertNotNull(orderType,"订单类型不能为空!");
        AssertUtil.assertNotNull(userId,"微信用户ID不能为空!");
        AssertUtil.assertNotNull(refundsId,"售后ID不能为空!");
        String refundNum = OrderNumUtil.createUniqueOrderNum();
        //退款
        BigDecimal amount = request.getRefundPrice();
        if (ZERO.equals(amount) || amount == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "退款金额有误!");
        }
        //获取当前可用积分
        PointsVO pointsVO = pointsService.selectPointInfo(userId);
        //可用积分
        Long availablePoints = pointsVO.getAvailablePoints();
        if (amount.longValue()>availablePoints){//如果退款金额大于剩余可用积分  那么按照100积分=2元的比例来对退款金额进行扣除
            //积分归0
            PointsUseBillRequest useBillRequest = new PointsUseBillRequest();
            useBillRequest.setUserId(userId);
            useBillRequest.setTitle(CONSUMPTION_REFUND.getType());
            useBillRequest.setConsumeMode(TUI_KUAN.getType());
            useBillRequest.setConsumePonts(availablePoints.intValue());
            useBillRequest.setCreateUser(userId);
            useBillRequest.setCreateTime(new Date());
            pointsService.consumPoint(useBillRequest);
            //剩余待换算成钱的积分 1积分=0.02元
            BigDecimal point = new BigDecimal(amount.longValue() - availablePoints);
            amount = amount.subtract(point.multiply(MONEY));
        }else {
            //积分归0
            PointsUseBillRequest useBillRequest = new PointsUseBillRequest();
            useBillRequest.setUserId(userId);
            useBillRequest.setTitle(CONSUMPTION_REFUND.getType());
            useBillRequest.setConsumeMode(TUI_KUAN.getType());
            useBillRequest.setConsumePonts(amount.intValue());
            useBillRequest.setCreateUser(userId);
            useBillRequest.setCreateTime(new Date());
            pointsService.consumPoint(useBillRequest);
        }
        //RAS扫描芯片  将书籍编码重新置为未出售状态
        if (BOOK.getType().toString().equals(orderType) || CART.getType().toString().equals(orderType) || INTEGRAL.getType().toString().equals(orderType)){
            List<MallRefundArticlesDO> list = refundArticlesService.lambdaQuery()
                    .eq(MallRefundArticlesDO::getRefundId, refundsId)
                    .eq(MallRefundArticlesDO::getArticlesCategory,BOOK.getType())
                    .list();
            if (CollectionUtils.isNotEmpty(list)) {
                List<MallRefundArticlesDO> bookList = list.stream().filter(item -> BOOK.getType().equals(item.getArticlesCategory())).collect(Collectors.toList());
                List<String> rasCode = request.getRasCode();
                AssertUtil.assertNotEmpty(rasCode, "书籍编码不能为空!");
                AssertUtil.assertTrue(bookList.size() == rasCode.size(), "书记编码数量与售后书籍数量不一致");
                booksRasService.lambdaUpdate()
                        .set(MallBooksRasDO::getIsSell, NOT_SELL.getType())
                        .in(MallBooksRasDO::getRasCode, rasCode)
                        .update();
            }
        }
        //修改售后状态
        MallRefundsDO refundsDO = new MallRefundsDO();
        refundsDO.setId(refundsId);
        refundsDO.setStatus(OrderRefundEnum.WAN_CHENG.getType());
        refundsDO.setAdminId(adminUserId);
        refundsDO.setUpdateTime(new Date());
        refundsDO.setUpdateUser(adminUserId);
        mallRefundsMapper.updateDO(refundsDO);
        if(BOOK.getType().toString().equals(orderType)){
            mallBookOrderService.lambdaUpdate()
                    .set(MallBooksOrderDO::getStatus,BEFOR_SALE.getType())
                    .eq(MallBooksOrderDO::getId,orderId)
                    .update();
        }
        if(RIM.getType().toString().equals(orderType)){
            periodOrderService.lambdaUpdate()
                    .set(MallPeripheryOrderDO::getStatus,BEFOR_SALE.getType())
                    .eq(MallPeripheryOrderDO::getId,orderId)
                    .update();
        }
        if(INTEGRAL.getType().toString().equals(orderType)){
            integrationOrderService.lambdaUpdate()
                    .set(MallIntegrationOrderDO::getStatus,BEFOR_SALE.getType())
                    .eq(MallIntegrationOrderDO::getId,orderId)
                    .update();
        }
        if(CART.getType().toString().equals(orderType)){
            cartOrderService.lambdaUpdate()
                    .set(ShoppingCartOrderDO::getStatus,BEFOR_SALE.getType())
                    .eq(ShoppingCartOrderDO::getId,orderId)
                    .update();
        }
        long fen = MoneyUtil.yuan2fen(amount.doubleValue());
        WeixinJsRefundOrderReq req = new WeixinJsRefundOrderReq();
        req.setTransaction_id(wxOrderNum);
        req.setOut_refund_no(refundNum);
        req.setReason("退货");
        RefundAmount refundAmount = new RefundAmount();
        refundAmount.setRefund(fen);
        req.setAmount(refundAmount);
        try {
            WeixinJsRefundOrderRes refundOrder = weixinJsClient.createRefundOrder(req);
            String status = refundOrder.getStatus();
            if ("SUCCESS".equals(status)){
                wechatRefund.setOrderId(request.getOrderId());
                wechatRefund.setOrderType(Integer.valueOf(request.getOrderType()));
                wechatRefund.setOrderNum(request.getOrderNum());
                wechatRefund.setRefundNum(refundNum);
                wechatRefund.setQuantity(request.getQuantity());
                redisCacheService.hashPushHashMap(ORDER_REFUND.name(),refundNum,wechatRefund,EXPIRE_SECONDS, TimeUnit.SECONDS);
            }else {
                throw new BusinessException(ErrorCode.ERR_REFUND, "微信退款失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.ERR_REFUND, "微信退款失败!");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deliverChangeGoods(AdminMallLogisticsRequest request) {
        Long adminUserId = SessionContext.getAdminUserId();
        Long orderId = request.getOrderId();
        Integer orderCategory = request.getOrderCategory();
        Integer num = request.getQuantity();
        String name = request.getName();
        Long addressId = request.getAddressId();
        BigDecimal weight = request.getWeight();
        BigDecimal volume = request.getVolume();
        Long refundsId = request.getRefundsId();
        AssertUtil.assertNotNull(refundsId,"售后ID不能为空!");
        AssertUtil.assertNotNull(addressId,"地址ID不能为空!");
        AssertUtil.assertNotNull(weight,"商品重量不能为空!");
        AssertUtil.assertNotNull(volume,"包裹体积不能为空!");
        AssertUtil.assertNotNull(name,"商品描述不能为空!");
        AssertUtil.assertNotNull(num,"包裹数量不能为空!");
        AssertUtil.assertNotNull(orderId,"订单ID不能为空!");
        AssertUtil.assertNotNull(orderCategory,"订单类别不能为空!");
        //书籍编码表状态修改为已出售
        if (BOOK.getType().equals(orderCategory)){
            List<String> rasCodeList = request.getRasCodeList();
            AssertUtil.assertNotEmpty(rasCodeList,"书籍RAS编码不能为空!");
            MallRefundArticlesDO articlesDO = refundArticlesService.lambdaQuery().eq(MallRefundArticlesDO::getRefundId, refundsId).one();
            Long sum = articlesDO.getQuantity();
            if (rasCodeList.size()!=sum.intValue()){
                throw new BusinessException(ErrorCode.PARAM_ERROR, "RAS编码数量与书籍换货数量不一致!");
            }
            List<MallBooksRasDO> rasDOS = booksRasService.lambdaQuery()
                    .eq(MallBooksRasDO::getIsSell, TRUE.getCode())
                    .in(MallBooksRasDO::getRasCode, rasCodeList)
                    .list();
            Long specificationId = articlesDO.getSpecificationId();
            List<MallBooksRasDO> rasDOList = booksRasService.lambdaQuery()
                    .eq(MallBooksRasDO::getIsSell, FALSE.getCode())
                    .eq(MallBooksRasDO::getSpecificationId,specificationId)
                    .in(MallBooksRasDO::getRasCode, rasCodeList)
                    .list();
            List<String> collect = rasDOS.stream().map(MallBooksRasDO::getRasCode).collect(Collectors.toList());
            AssertUtil.assertFalse(CollectionUtils.isNotEmpty(rasDOS),"扫描的书籍编码存在已售卖的编码->{"+ JSONObject.toJSONString(collect)+"}");
            AssertUtil.assertFalse(CollectionUtils.isEmpty(rasDOList),"扫描的书籍非原订单书籍的规格!");
            AssertUtil.assertFalse(rasDOList.size()!=rasCodeList.size(),"扫描的书籍与原订单书籍的规格不一致,请检查!");
            booksRasService.lambdaUpdate()
                    .set(MallBooksRasDO::getIsSell,TRUE.getCode())
                    .set(MallBooksRasDO::getUpdateTime,new Date())
                    .eq(MallBooksRasDO::getMallBooksId,articlesDO.getArticlesId())
                    .in(MallBooksRasDO::getRasCode,rasCodeList)
                    .update();
        }else if (CART.getType().equals(orderCategory)){
            List<MallRefundArticlesDO> articlesDOs = refundArticlesService.lambdaQuery()
                    .eq(MallRefundArticlesDO::getRefundId, refundsId)
                    .eq(MallRefundArticlesDO::getArticlesCategory,BOOK.getType())
                    .list();
            if (CollectionUtils.isNotEmpty(articlesDOs)){
                List<String> rasCodeList = request.getRasCodeList();
                AssertUtil.assertNotEmpty(rasCodeList,"书籍RAS编码不能为空!");
                Long sum = articlesDOs.stream().mapToLong(MallRefundArticlesDO::getQuantity).sum();
                if (rasCodeList.size()!=sum.intValue()){
                    throw new BusinessException(ErrorCode.PARAM_ERROR, "RAS编码数量与书籍换货数量不一致!");
                }
                List<MallBooksRasDO> rasDOS = booksRasService.lambdaQuery()
                        .eq(MallBooksRasDO::getIsSell, TRUE.getCode())
                        .in(MallBooksRasDO::getRasCode, rasCodeList)
                        .list();
                List<String> collect = rasDOS.stream().map(MallBooksRasDO::getRasCode).collect(Collectors.toList());
                AssertUtil.assertFalse(CollectionUtils.isNotEmpty(rasDOS),"扫描的书记编码存在已售卖的编码->{"+ JSONObject.toJSONString(collect)+"}");
                List<Long> specificationIds = articlesDOs.stream().map(MallRefundArticlesDO::getSpecificationId).collect(Collectors.toList());
                List<MallBooksRasDO> rasDOList = booksRasService.lambdaQuery()
                        .eq(MallBooksRasDO::getIsSell, FALSE.getCode())
                        .in(MallBooksRasDO::getSpecificationId,specificationIds)
                        .in(MallBooksRasDO::getRasCode, rasCodeList)
                        .list();
                AssertUtil.assertFalse(CollectionUtils.isEmpty(rasDOList),"扫描的书籍非原订单书籍的规格!");
                AssertUtil.assertFalse(rasDOList.size()!=rasCodeList.size(),"扫描的书籍与原订单书籍的规格不一致,请检查!");
                List<Long> bookIds = articlesDOs.stream().map(MallRefundArticlesDO::getArticlesId).collect(Collectors.toList());
                booksRasService.lambdaUpdate()
                        .set(MallBooksRasDO::getIsSell,TRUE.getCode())
                        .set(MallBooksRasDO::getUpdateTime,new Date())
                        .in(MallBooksRasDO::getMallBooksId,bookIds)
                        .in(MallBooksRasDO::getRasCode,rasCodeList)
                        .update();
            }
        }else if (INTEGRAL.getType().equals(orderCategory)) {
            MallRefundArticlesDO articlesDO = refundArticlesService.lambdaQuery().eq(MallRefundArticlesDO::getRefundId, refundsId).one();
            Integer articlesCategory = articlesDO.getArticlesCategory();
            if (BOOK.getType().equals(articlesCategory)) {
                List<String> rasCodeList = request.getRasCodeList();
                AssertUtil.assertNotEmpty(rasCodeList,"书籍RAS编码不能为空!");
                Long sum = articlesDO.getQuantity();
                if (rasCodeList.size()!=sum.intValue()){
                    throw new BusinessException(ErrorCode.PARAM_ERROR, "RAS编码数量与书籍换货数量不一致!");
                }
                List<MallBooksRasDO> rasDOS = booksRasService.lambdaQuery()
                        .eq(MallBooksRasDO::getIsSell, TRUE.getCode())
                        .in(MallBooksRasDO::getRasCode, rasCodeList)
                        .list();
                List<String> collect = rasDOS.stream().map(MallBooksRasDO::getRasCode).collect(Collectors.toList());
                AssertUtil.assertFalse(CollectionUtils.isNotEmpty(rasDOS), "扫描的书记编码存在已售卖的编码->{" + JSONObject.toJSONString(collect) + "}");
                Long specificationId = articlesDO.getSpecificationId();
                List<MallBooksRasDO> rasDOList = booksRasService.lambdaQuery()
                        .eq(MallBooksRasDO::getIsSell, FALSE.getCode())
                        .eq(MallBooksRasDO::getSpecificationId,specificationId)
                        .in(MallBooksRasDO::getRasCode, rasCodeList)
                        .list();
                AssertUtil.assertFalse(CollectionUtils.isEmpty(rasDOList),"扫描的书籍非原订单书籍的规格!");
                AssertUtil.assertFalse(rasDOList.size()!=rasCodeList.size(),"扫描的书籍与原订单书籍的规格不一致,请检查!");
                booksRasService.lambdaUpdate()
                        .set(MallBooksRasDO::getIsSell, TRUE.getCode())
                        .set(MallBooksRasDO::getUpdateTime, new Date())
                        .eq(MallBooksRasDO::getMallBooksId, articlesDO.getArticlesId())
                        .in(MallBooksRasDO::getRasCode, rasCodeList)
                        .update();
            }
        }
        //新增商家物流信息
        String logisticsOrderNum = "SCSH" + OrderNumUtil.createJdUniqueOrderNum();
        MallLogisticsRequest logisticsRequest = new MallLogisticsRequest();
        logisticsRequest.setOrderId(orderId);
        logisticsRequest.setLogisticsNum(logisticsOrderNum);
        logisticsRequest.setAddressId(addressId);
        logisticsRequest.setOrderType(orderCategory);
        logisticsRequest.setShippingDate(new Date());
        logisticsRequest.setShippingMethod("JD");
        logisticsRequest.setFreeType(HUAN_HUO_SHIPING.getType());
        //JD物流前置校验
        AddressDO addressDO = addressService.lambdaQuery().eq(AddressDO::getId, addressId).one();
        jdPreCheck(addressId,addressDO);
        //物流下单
        CommonCreateOrderResponse commonCreateOrderResponse = creatJDOrder(num, name, addressId, weight, volume, logisticsOrderNum);
        String orderCode = commonCreateOrderResponse.getOrderCode();
        String waybillCode = commonCreateOrderResponse.getWaybillCode();
        logisticsRequest.setCreateTime(new Date());
        logisticsRequest.setCreateUser(SessionContext.getAdminUserId());
        logisticsRequest.setLogisticsOrderId(orderCode);
        logisticsRequest.setWaybillCode(waybillCode);
        logisticsRequest.setFreight(commonCreateOrderResponse.getFreightPre());
        logisticsService.add(logisticsRequest);
        //修改售后状态
        MallRefundsDO refundsDO = new MallRefundsDO();
        refundsDO.setId(refundsId);
        refundsDO.setStatus(OrderRefundEnum.YUN_SHU.getType());
        refundsDO.setAdminId(adminUserId);
        refundsDO.setUpdateTime(new Date());
        refundsDO.setUpdateUser(adminUserId);
        mallRefundsMapper.updateDO(refundsDO);
        //订阅物流轨迹
        SubscribeTraceRequest traceRequest = new SubscribeTraceRequest();
        String mobile = addressDO.getMobile();
        String lastFourDigits = mobile.substring(mobile.length() - 4);
        traceRequest.setMobile(lastFourDigits);
        traceRequest.setWaybillCode(waybillCode);
        traceRequest.setOrderCode(orderCode);
        traceRequest.setOrderOrigin(1);
        traceRequest.setCustomerCode(jdProperties.getCustomerCode());
        Response<String> subscribeTrace = jdClient.subscribeTrace(traceRequest);
        log.info("JD物流轨迹信息订阅结果,为空则订阅失败->{}",subscribeTrace.getData());
        return true;
    }

    private CommonCreateOrderResponse creatJDOrder(Integer num, String name, Long addressId, BigDecimal weight, BigDecimal volume, String logisticsOrderNum) {
        CreateOrderRequest createOrderRequest = new CreateOrderRequest();
        //商家物流订单编号
        createOrderRequest.setOrderId(logisticsOrderNum);

        Contact sender = new Contact();
        sender.setName("张先生");
        sender.setMobile("18981732326");
        sender.setFullAddress("北京大兴区亦庄经济开发区京东总部2号楼B座");
        createOrderRequest.setSenderContact(sender);

        AddressDO addressDO = addressService.lambdaQuery().eq(AddressDO::getId, addressId).one();
        Contact receiver = new Contact();
        receiver.setName("王先生");
        receiver.setMobile("18981732326");
        receiver.setFullAddress("北京大兴区亦庄经济开发区京东总部2号楼B座");
        //@TODO:后面放开
//        receiver.setName(addressDO.getReceiver());
//        receiver.setMobile(addressDO.getMobile());
//        receiver.setFullAddress(addressDO.getProvince()+addressDO.getCity()+addressDO.getArea()+addressDO.getDetail());
        createOrderRequest.setReceiverContact(receiver);

        createOrderRequest.setOrderOrigin(1);
        createOrderRequest.setCustomerCode(jdProperties.getCustomerCode());

        CommonProductInfo productInfo = new CommonProductInfo();
        productInfo.setProductCode("ed-m-0001");
        createOrderRequest.setProductsReq(productInfo);

        createOrderRequest.setSettleType(3);

        List<CommonCargoInfo> cargoInfos = Lists.newArrayList();
        CommonCargoInfo cargoInfo = new CommonCargoInfo();
        cargoInfo.setName(name);
        cargoInfo.setQuantity(num);
        cargoInfo.setWeight(weight);
        cargoInfo.setVolume(volume);
        cargoInfos.add(cargoInfo);
        createOrderRequest.setCargoes(cargoInfos);
        createOrderRequest.setRemark("测试单，勿接单");
        CommonCreateOrderResponse commonCreateOrderResponse = jdClient.create(createOrderRequest);
        return commonCreateOrderResponse;
    }

    private void jdPreCheck(Long addressId, AddressDO addressDO) {
        PreCheckRequest preCheckRequest = new PreCheckRequest();
        Contact sender = new Contact();
        sender.setFullAddress("河北省廊坊市广阳区万庄镇中心小学");
        preCheckRequest.setSenderContact(sender);

        Contact receiver = new Contact();
//        @TODO:后面放开  receiver.setFullAddress(addressDO.getProvince()+addressDO.getCity()+addressDO.getArea()+addressDO.getDetail());
        receiver.setFullAddress("河北省廊坊市广阳区万庄镇中心小学");
        preCheckRequest.setReceiverContact(receiver);

        preCheckRequest.setOrderOrigin(1);
        preCheckRequest.setCustomerCode(jdProperties.getCustomerCode());

        CommonProductInfo productInfo = new CommonProductInfo();
        productInfo.setProductCode("ed-m-0001");
        preCheckRequest.setProductsReq(productInfo);
        jdClient.preCheck(preCheckRequest);
    }

}
